class RateableObject < ActiveRecord::Base
  has_many :ratings, :dependent => :destroy

  ITEMS_PER_PAGE = 500
  
  TYPES = %w(
    song
    book
    film
    website
  )

  validates_inclusion_of :rateable_type, :in => TYPES
  def validate_on_create 
    case self.rateable_type
      when "song", "book"
        errors.add_on_blank( ["name", "creator"] )
      when "film", "website"
        errors.add_on_blank( ["name"] )
    end
  end

  def self.get_items(params = {}, count = ITEMS_PER_PAGE, page = nil)
    conditions = []
    conditions << ["published = ?", 1]
    conditions << ["rateable_type = ?", params[:type]] if params[:type] && TYPES.include?(params[:type])
    ["name", "creator", "genre"].each do |param_name|
      value = params[param_name.to_sym]
      conditions << ["#{param_name} like ?", value] if value
    end
    
    order = 
      if params[:order]
        # Use name as secondary sort if custom sort is provided.  
        params[:order].include?("name") ? params[:order] : "#{params[:order]}, name ASC"
      else
        "created_at DESC"
      end
    
    # Translate to something Rails understands
    translated_conditions = conditions.collect { |c| c[1] }
    translated_conditions.insert(0, conditions.collect{ |c| c[0] } * ' AND ')
  
    page = page.to_i
    find(
      :all,
      :conditions => translated_conditions,
      :include    => :ratings,
      :limit      => count,
      :offset     => count * page,
      :order      => order
    )
  end
  
  def self.get_types
    TYPES
  end
  
  def self.get_creators
    find_by_sql <<-SQL
      SELECT DISTINCT(creator)
      FROM #{RateableObject.table_name}
      WHERE published = 1
    SQL
  end
  
  def self.get_genres
    find_by_sql <<-SQL
      SELECT DISTINCT(genre)
      FROM #{RateableObject.table_name}
      WHERE published = 1
    SQL
  end
  
  def rating_average
    ratings.size == 0 ?
      0 :
      ratings.collect { |r| r.score }.inject(0.0) { |result, el| result + el } / ratings.size
  end
  
  def rating_eusden
    e = ratings.select { |r| r.guid == SECRET["guid"] }.first
    e ? e.score.to_i : 0
  end
  
  def hide
    self.published = 0
    self.save
  end
  
  def update_average_score
    total = 0.0
    self.ratings.each do |r|
      total += r.score.to_i
    end
    
    self.average_score = total / self.ratings.size
    self.save
  end
end
